import fs from 'fs';
import os from 'os';
import path from 'path';
import readline from 'readline';
import process from 'process';
import chalk from 'chalk';
import {spawn} from 'child_process';
import {createLogger} from '../utils/Logger.js';

const logger = createLogger('CODEX-CC');
const CODEX_DIR = path.join(os.homedir(), '.codex');
const AUTH_FILE = path.join(CODEX_DIR, 'auth.json');
const STORE_FILE = path.join(CODEX_DIR, 'codex-cc.json');
const LEGACY_PATTERN = /^auth_(.+)\.json$/;
const POLL_INTERVAL_MS = 1000;
const POLL_TIMEOUT_MS = 60 * 60 * 1000;

export async function execute(args = []) {
    const [command, ...rest] = args;
    ensureCodexDir();
    const store = loadStore();
    await migrateLegacyIfNeeded(store);

    if (!command) {
        await handleInteractiveSwitch(store);
        return;
    }
    if (command === 'clear') {
        await handleClear();
        return;
    }
    if (command === 'add') {
        await handleAdd(store, rest);
        return;
    }
    await handleSwitch(store, command, {runCodexAfter: true});
}

async function handleInteractiveSwitch(store) {
    const profiles = Object.keys(store.profiles || {});
    if (profiles.length === 0) {
        logger.warn('未发现可用配置，请先通过 codex 登录并执行 codex-cc add <名称>。');
        process.exitCode = 1;
        return;
    }
    const current = store.current || null;
    const selected = await promptProfile(profiles, current);
    if (!selected) {
        logger.warn('未选择任何配置，操作已取消。');
        process.exitCode = 1;
        return;
    }
    await writeAuthFromStore(store, selected);
    store.current = selected;
    saveStore(store);
}

async function handleClear() {
    if (!fs.existsSync(AUTH_FILE)) {
        logger.info('未检测到 ~/.codex/auth.json，无需清理。');
        return;
    }
    try {
        fs.unlinkSync(AUTH_FILE);
        logger.success('已删除 ~/.codex/auth.json');
    } catch (error) {
        logger.error(`删除 ~/.codex/auth.json 失败: ${error.message}`);
        process.exitCode = 1;
    }
}

async function handleAdd(store, params) {
    const [profileName] = params;
    if (!profileName) {
        logger.error('请使用: codex-cc add <配置名称>');
        process.exitCode = 1;
        return;
    }
    removeAuthIfExists();
    logger.info('准备启动 codex 生成新的授权文件...');
    const exitCode = await runCodex();
    if (exitCode !== 0) {
        logger.error(`codex 退出码: ${exitCode}`);
        process.exitCode = exitCode || 1;
        return;
    }
    logger.info('开始轮询 ~/.codex/auth.json，最长等待 1 小时...');
    const ready = await waitForFile(AUTH_FILE, POLL_TIMEOUT_MS, POLL_INTERVAL_MS);
    if (!ready) {
        logger.error('1 小时内未检测到 ~/.codex/auth.json，已停止等待。');
        process.exitCode = 1;
        return;
    }
    const data = readAuthData();
    if (!data) {
        process.exitCode = 1;
        return;
    }
    store.profiles[profileName] = {
        data,
        savedAt: new Date().toISOString()
    };
    store.current = profileName;
    saveStore(store);
    logger.success(`已保存配置 ${profileName} 至 ${STORE_FILE}`);
}

async function handleSwitch(store, profileName, options = {}) {
    if (!store.profiles[profileName]) {
        logger.error(`配置 ${profileName} 不存在，请先执行 codex-cc add ${profileName}`);
        process.exitCode = 1;
        return;
    }
    await writeAuthFromStore(store, profileName);
    store.current = profileName;
    saveStore(store);
    if (options.runCodexAfter) {
        const exitCode = await runCodex();
        if (exitCode !== 0) {
            logger.error(`codex 退出码: ${exitCode}`);
            process.exitCode = exitCode || 1;
        }
    }
}

async function writeAuthFromStore(store, profileName) {
    const profile = store.profiles[profileName];
    if (!profile || !profile.data) {
        logger.error(`配置 ${profileName} 数据为空或缺失，无法写入 auth.json`);
        process.exitCode = 1;
        return;
    }
    try {
        fs.writeFileSync(AUTH_FILE, JSON.stringify(profile.data, null, 2), 'utf-8');
        logger.success(`已切换至 ${profileName} 配置并生成 ~/.codex/auth.json`);
    } catch (error) {
        logger.error(`写入 ~/.codex/auth.json 失败: ${error.message}`);
        process.exitCode = 1;
    }
}

function ensureCodexDir() {
    if (!fs.existsSync(CODEX_DIR)) {
        fs.mkdirSync(CODEX_DIR, {recursive: true});
    }
}

function loadStore() {
    if (!fs.existsSync(STORE_FILE)) {
        return {current: null, profiles: {}};
    }
    try {
        const raw = fs.readFileSync(STORE_FILE, 'utf-8');
        const parsed = JSON.parse(raw);
        return {
            current: parsed.current ?? null,
            profiles: parsed.profiles ?? {}
        };
    } catch (error) {
        logger.warn(`读取 ${STORE_FILE} 失败，已重置为空: ${error.message}`);
        return {current: null, profiles: {}};
    }
}

function saveStore(store) {
    try {
        fs.writeFileSync(STORE_FILE, JSON.stringify(store, null, 2), 'utf-8');
    } catch (error) {
        logger.error(`保存 ${STORE_FILE} 失败: ${error.message}`);
        process.exitCode = 1;
    }
}

async function migrateLegacyIfNeeded(store) {
    const legacyFiles = fs.readdirSync(CODEX_DIR)
        .filter(name => LEGACY_PATTERN.test(name));
    let migrated = false;
    for (const fileName of legacyFiles) {
        const match = LEGACY_PATTERN.exec(fileName);
        const profileName = match?.[1];
        if (!profileName || store.profiles[profileName]) {
            continue;
        }
        const filePath = path.join(CODEX_DIR, fileName);
        try {
            const content = fs.readFileSync(filePath, 'utf-8');
            const data = JSON.parse(content);
            store.profiles[profileName] = {
                data,
                savedAt: new Date().toISOString()
            };
            migrated = true;
            logger.info(`已导入历史配置 ${profileName} (${fileName})`);
        } catch (error) {
            logger.warn(`导入 ${fileName} 失败，已跳过: ${error.message}`);
        }
    }
    if (!store.current && fs.existsSync(AUTH_FILE)) {
        const data = readAuthData();
        if (data) {
            const profileName = 'default';
            store.profiles[profileName] = {
                data,
                savedAt: new Date().toISOString()
            };
            store.current = profileName;
            migrated = true;
            logger.info('已导入当前 auth.json 为 default 配置');
        }
    }
    if (migrated) {
        saveStore(store);
    }
}

function promptProfile(profiles, currentProfile) {
    return new Promise(resolve => {
        console.log(chalk.cyan('请选择要切换的数据来源:'));
        profiles.forEach((name, index) => {
            const currentMark = name === currentProfile ? ' (当前)' : '';
            console.log(`  [${index + 1}] ${name}${currentMark}`);
        });
        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });
        const ask = () => {
            rl.question('输入序号或名称（q 取消）：', answer => {
                const value = (answer || '').trim();
                if (!value || value.toLowerCase() === 'q') {
                    rl.close();
                    resolve(null);
                    return;
                }
                const index = Number.parseInt(value, 10);
                if (!Number.isNaN(index) && index >= 1 && index <= profiles.length) {
                    rl.close();
                    resolve(profiles[index - 1]);
                    return;
                }
                const matched = profiles.find(name => name === value);
                if (matched) {
                    rl.close();
                    resolve(matched);
                    return;
                }
                console.log(chalk.yellow('无效输入，请重新选择。'));
                ask();
            });
        };
        ask();
    });
}

function waitForFile(targetPath, timeoutMs, intervalMs) {
    const start = Date.now();
    return new Promise(resolve => {
        const timer = setInterval(() => {
            if (fs.existsSync(targetPath)) {
                clearInterval(timer);
                resolve(true);
                return;
            }
            if (Date.now() - start >= timeoutMs) {
                clearInterval(timer);
                resolve(false);
            }
        }, intervalMs);
    });
}

function runCodex() {
    return new Promise((resolve, reject) => {
        const child = spawn('codex', {
            stdio: 'inherit',
            shell: process.platform === 'win32'
        });
        child.on('error', error => {
            logger.error(`启动 codex 失败: ${error.message}`);
            reject(error);
        });
        child.on('exit', code => {
            resolve(typeof code === 'number' ? code : 0);
        });
    }).catch(() => {
        process.exitCode = 1;
        return 1;
    });
}

function readAuthData() {
    try {
        const content = fs.readFileSync(AUTH_FILE, 'utf-8');
        return JSON.parse(content);
    } catch (error) {
        logger.error(`读取 ~/.codex/auth.json 失败: ${error.message}`);
        return null;
    }
}

function removeAuthIfExists() {
    if (fs.existsSync(AUTH_FILE)) {
        try {
            fs.unlinkSync(AUTH_FILE);
        } catch (error) {
            logger.error(`删除 ~/.codex/auth.json 失败: ${error.message}`);
            process.exitCode = 1;
        }
    }
}
